﻿using AFanDa.BLL.BaseService;
using AFanDa.Dto.Base;
using AFanDa.Dto.Request;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace AFanDa.BLL.BLLService
{
    public class OrderService
    {
        private readonly BaseOrderService _baseOrdersService = null;
        private readonly BaseOrderDetailsService _baseOrderDetailsService = null;
        private readonly BasePayService _payService = null;
        private readonly BaseGoods _baseGoodsService = null;
        private readonly BasePayService _baseService = null;
        private readonly BaseTableService _baseTableService = null;

        public OrderService()
        {
            _baseOrdersService = new BaseOrderService();
            _baseOrderDetailsService = new BaseOrderDetailsService();
            _payService = new BasePayService();
            _baseGoodsService = new BaseGoods();
            _baseTableService = new BaseTableService();
            _baseService = new BasePayService();
        }


        /// <summary>
        /// 创建订单的过程
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public ApiResult CreateOrder(OrderRequestDto dto)
        {


            var ord = _baseOrdersService.QueryAll(d => dto.Tid == d.OTID && d.OID == dto.id && d.OState != 1 && d.OState != 0);
            if (ord.Any())
            {
                var order = ord.Single();

                decimal? money = 0;

                int? sum = 0;




                List<Dto.EF.OrdersDetails> details = new List<Dto.EF.OrdersDetails>();
                dto.details.ToList().ForEach(d =>
                {

                    var orderdetails = order.OrdersDetails.Where(od => od.ODGID.Contains(d.good.id) && od.ODOID == order.OID && od.ODIsPay == -1);
                    if (orderdetails.Any())
                    {
                        var ods = orderdetails.Single();
                        ods.ODCount += d.num;
                        ods.ODPrice += d.num * d.good.price;
                        money += d.num * d.good.price;
                        sum += d.num;
                    }
                    else
                    {
                        details.Add(new Dto.EF.OrdersDetails
                        {
                            ODOID = order.OID,
                            ODID = Common.Config.GUID(),
                            ODCount = d.num,
                            ODFid = d.flavor != null ? d.flavor.id : null,
                            ODGID = d.good.id,
                            ODIsPay = -1,
                            ODCreateTime = DateTime.Now,
                            ODPrice = d.num * d.good.price,
                            ODState = 1,
                            ODPayType = dto.PayType

                        });
                    }

                });

                details.ForEach((item) =>
                {
                    money += item.ODPrice;
                    sum += item.ODCount;
                    order.OrdersDetails.Add(item);
                });

                order.OState = 2;
                order.OIsPay = -1;
                order.OMoney += money;

                order.OCount += sum;

                var result = _baseOrdersService.SaveChange();

                if (result > 0)
                {

                    var table = _baseTableService.QueryAll(d => d.Tid == dto.Tid).Single();


                    table.Tstatus = 1;

                    _baseTableService.Update(table);


                    _baseTableService.SaveChange();
                    return new ApiResult()
                    {

                        code = ApiCode.ok,
                        message = "生成订单",
                        data = new
                        {

                            oid = order.OID,
                        }
                    };

                }

            }
            else
            {



                string oid = Common.Config.GUID();
                string ONumber = DateTime.Now.ToString("yyyyMMddhhmmss");
                var gids = dto.details.Select(d => d.good.id).ToList();

                var iq = _baseGoodsService.QueryAll(d => gids.Contains(d.Gid));
                if (!iq.Any())
                {
                    return new ApiResult()
                    {
                        code = ApiCode.fail,
                        message = "参数错误"
                    };
                }






                decimal? money = 0;
                List<Dto.EF.OrdersDetails> details = new List<Dto.EF.OrdersDetails>();
                dto.details.ToList().ForEach(d =>
                {
                    details.Add(new Dto.EF.OrdersDetails
                    {
                        ODOID = oid,
                        ODID = Common.Config.GUID(),
                        ODCount = d.num,
                        ODFid = d.flavor != null ? d.flavor.id : null,
                        ODGID = d.good.id,
                        ODIsPay = -1,
                        ODCreateTime = DateTime.Now,
                        ODPrice = d.num * d.good.price,
                        ODState = 1,
                        ODPayType = dto.PayType,

                    });
                });

                details.ForEach((item) =>
                {
                    money += item.ODPrice;
                });

                DateTime now = DateTime.Now;

                Dto.EF.Orders order = new Dto.EF.Orders()
                {
                    ONumBer = ONumber,
                    OID = oid,
                    OCount = gids.Count,
                    OCreaTime = now,
                    OWXUID = dto.WxUid,
                    OIsPay = -1,
                    OState = dto.WxUid == null ? 2 : 3,
                    OIsVip = 0,
                    OMoney = money,
                    OPayTime = null,
                    OTID = dto.Tid,
                    OType = dto.Type,
                    OrdersDetails = details,
                    Ooccupy = dto.occupy,
                    ORemark = dto.remark,
                    OPhone = dto.phone,
                    OBeginTime = now,
                    OEndTime = now.AddMinutes(5),
                    OPayType = dto.PayType
                };

                _baseOrdersService.Add(order);
                var result = _baseOrdersService.SaveChange();

                if (result > 0)
                {



                    var table = _baseTableService.QueryAll(d => d.Tid == dto.Tid).Single();

                    table.Toccupy += order.Ooccupy;
                    table.Tstatus = 1;

                    _baseTableService.Update(table);


                    _baseTableService.SaveChange();


                }




                return new ApiResult()
                {

                    code = ApiCode.ok,
                    message = "生成订单",
                    data = new
                    {
                        ONumber = ONumber,
                        oid = oid,
                    }
                };
            }


            return new ApiResult()
            {

                code = ApiCode.fail,
                message = "生成失败",


            };
        }

        /// <summary>
        /// 获取单个订单详情
        /// </summary>
        /// <param name="Dto"></param>
        /// <returns></returns>
        public ApiResult GetOrderInfo(OrderRequestDto dto)
        {

            DateTime now = DateTime.Now;
            var iq = _baseOrdersService.QueryAll(d => d.OID == dto.id);
            if (iq.Any())
            {
                var order = iq.Single();

                var data = new Dto.Reponse.OrderResponseDto()
                {
                    id = order.OID,
                    PaidInMoney = 0,
                    isPay = order.OIsPay,
                    PayType = order.OPayType,
                    state = order.OState,
                    createTime = order.OCreaTime.Value.ToString(),
                    money = order.OMoney,
                    Number = order.ONumBer,
                    occupy = order.Ooccupy,
                    phone = order.OPhone,
                    Remark = order.ORemark,
                    Tid = order.tables.Tid,
                    UserName = order.WxUser == null ? null : order.WxUser.UName,
                    GuoQiTime = now > order.OEndTime ? "00:00:00" : (order.OEndTime - now).Value.ToString(),
                    details = order.OrdersDetails.Select(o => new Dto.Reponse.OrderDetailsResponseDto()
                    {
                        isPay = o.ODIsPay,
                        id = o.ODID,
                        count = o.ODCount,
                        good = new Dto.Reponse.GoodsResponseDto()
                        {
                            id = o.goods.Gid,
                            name = o.goods.Gname,
                            price = o.goods.Gprice,
                            img = o.goods.GImg
                        },
                        flavor = o.flavor == null ? null : new Dto.Reponse.flavorResponseDto()
                        {
                            id = o.flavor.Fid,
                            name = o.flavor.Fname
                        }

                    }).ToList()
                };






                var iqor = order.OrdersDetails.Where(d => d.ODIsPay == -1);

                iqor.ToList().ForEach(d =>
                {
                    order.OPaidInMoney += d.ODCount * d.ODPrice;
                });


                return new ApiResult()
                {
                    code = ApiCode.ok,
                    message = "获取订单详情",
                    data = data
                };

            }
            else
            {
                return new ApiResult()
                {
                    code = ApiCode.fail,
                    message = "订单号错误",

                };
            }

        }

        /// <summary>
        /// 获取所有订单
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public ApiResult GetOrderByStatu(OrderRequestDto dto)
        {
            Expression<Func<Dto.EF.Orders, bool>> where = null;

            if (dto.Uid != null)
            {
                where = d => d.OWXUID == dto.Uid;
            }

            var iq = _baseOrdersService.QueryAll(where);
            var data = iq.Select(d => new Dto.Reponse.OrderResponseDto()
            {
                id = d.OID,
                isPay = d.OIsPay,
                PaidInMoney = d.OPaidInMoney,
                state = d.OState,
                createTime = d.OCreaTime.Value.ToString(),
                money = d.OMoney,
                Number = d.ONumBer,
                occupy = d.Ooccupy,
                phone = d.OPhone,
                Remark = d.ORemark,
                details = d.OrdersDetails.Select(o => new Dto.Reponse.OrderDetailsResponseDto()
                {
                    id = o.ODID,
                    count = o.ODCount,
                    good = new Dto.Reponse.GoodsResponseDto()
                    {
                        id = o.goods.Gid,
                        name = o.goods.Gname,
                        price = o.goods.Gprice,
                        img = o.goods.GImg
                    },
                    flavor = o.flavor == null ? null : new Dto.Reponse.flavorResponseDto()
                    {
                        id = o.flavor.Fid,
                        name = o.flavor.Fname
                    }

                }).ToList()
            }).ToList();




            return new ApiResult()
            {
                code = ApiCode.ok,
                message = "获取我的订单",
                data = data
            };

        }

        /// <summary>
        /// 修改订单状态
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public ApiResult UpdateOrderState(OrderRequestDto dto)
        {
            var iq = _baseOrdersService.QueryAll(d => d.OID == dto.id);

            if (!iq.Any())
            {
                return new ApiResult()
                {
                    code = ApiCode.fail,
                    message = "订单取消失败"
                };
            }

            var order = iq.Single();
            order.OID = dto.id;
            order.OState = dto.state;

            order.OIsPay = dto.isPay;

            _baseOrdersService.Update(order);

            var result = _baseOrdersService.SaveChange();

            if (result > 0)
            {

                var table = _baseTableService.QueryAll(d => d.Tid == order.OTID).Single();


                var iqy = _baseOrdersService.QueryAll(d => d.OTID == table.Tid && d.OState == 2 || d.OState == 3);

                if (iqy.Any())
                {
                    table.Toccupy -= order.Ooccupy;

                }
                else
                {
                    table.Toccupy = 0;
                    table.Tstatus = 0;
                }





                _baseTableService.Update(table);


                _baseTableService.SaveChange();


                return new ApiResult()
                {
                    code = ApiCode.ok,
                    message = "订单已取消"
                };
            }
            return new ApiResult()
            {
                code = ApiCode.fail,
                message = "订单取消失败"
            };






        }





        /// <summary>
        /// 支付  调用支付接口 生成支付连接 引导用户跳转完成支付后 则修改订单状态
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public ApiResult PayOrder(OrderRequestDto dto)
        {
            var iq = _baseOrdersService.QueryAll(d => d.OID == dto.id);
            if (!iq.Any())
            {
                //订单号错误
                return new ApiResult()
                {
                    code = ApiCode.fail,
                    message = "订单号错误"
                };
            }

            var order = iq.Single();

            Dto.EF.Pay pay = new Dto.EF.Pay()
            {
                PID = Common.Config.GUID(),
                POID = dto.id,
                PCreateTime = DateTime.Now,
                PMoney = dto.PaidInMoney,
                PResult = -1,
                PSumMoney = order.OMoney,
                PCards = null,
                PType = dto.PayType,
            };
            _payService.Add(pay);
            var result = _payService.SaveChange();



            if (result > 0)
            {
                pay.PResult = 1;


                _payService.Update(pay);
                _payService.SaveChange();

                order.OPayType = dto.PayType;
                order.OState = 3;


                List<Dto.EF.OrdersDetails> OrderDetails = order.OrdersDetails.ToList();








                OrderDetails.ForEach(d =>
                {
                    d.goods.Gnum -= d.ODCount;
                    d.ODIsPay = 0;
                });


                _baseOrdersService.Update(order);
                _baseOrdersService.SaveChange();




                return new ApiResult()
                {
                    code = ApiCode.ok,
                    message = "支付成功",
                    data = pay
                };
            }
            return new ApiResult()
            {
                code = ApiCode.fail,
                message = "支付失败"
            };

        }
        /// <summary>
        /// asdf
        /// </summary>
        /// <param name="Oid"></param>
        /// <returns></returns>
        public ApiResult DelGoods(string Oid)
        {
            var iq = _baseOrdersService.QueryAll(d => d.OID == Oid);

            if (iq.Any())
            {
                var order = iq.Single();


                List<Dto.EF.OrdersDetails> OrderDetails = order.OrdersDetails.ToList();

                OrderDetails.ForEach(d =>
                {
                    d.goods.Gnum -= d.ODCount;
                });



                _baseOrdersService.Update(order);

                _baseOrdersService.SaveChange();

                return new ApiResult()
                {

                    code = 0,

                };

            }
            return new ApiResult()
            {

                code = 0,

            };
        }




        /// <summary>
        /// 完成订单
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public ApiResult PayOK(OrderRequestDto dto)
        {
            var iq = _baseOrdersService.QueryAll(d => d.OID == dto.id);

            if (iq.Any())
            {
                var order = iq.Single();


                if (order.OWXUID == null)
                {

                    Dto.EF.Pay pay = new Dto.EF.Pay();

                    pay.PID = Common.Config.GUID();
                    pay.POID = order.OID;
                    //实付金额
                    pay.PMoney = dto.PaidInMoney;
                    pay.PCreateTime = DateTime.Now;
                    //总金额
                    pay.PSumMoney = order.OMoney;
                    pay.PCards = null;

                    pay.PResult = -1;
                    pay.PType = dto.PayType;


                    _payService.Add(pay);

                    var result = _payService.SaveChange();


                    if (result > 0)
                    {
                        pay.PResult = 1;


                        _payService.Update(pay);
                        _payService.SaveChange();

                        order.OState = 0;

                        order.OIsPay = 1;




                        List<Dto.EF.OrdersDetails> OrderDetails = order.OrdersDetails.ToList();

                        OrderDetails.ForEach(d =>
                        {
                            d.goods.Gnum -= d.ODCount;
                            d.ODPayType = dto.PayType;
                        });

                        _baseOrderDetailsService.UpdateRange(OrderDetails);
                        _baseOrderDetailsService.SaveChange();

                        _baseOrdersService.Update(order);
                        _baseOrdersService.SaveChange();

                        var table = _baseTableService.QueryAll(d => d.Tid == order.OTID).Single();

                        var iqy = _baseOrdersService.QueryAll(d => d.OTID == table.Tid && d.OState == 2 || d.OState == 3);

                        if (iqy.Any())
                        {
                            table.Toccupy -= order.Ooccupy;

                        }
                        else
                        {
                            table.Toccupy = 0;
                            table.Tstatus = 0;
                        }

                        _baseTableService.Update(table);
                        _baseTableService.SaveChange();

                        return new ApiResult()
                        {
                            code = ApiCode.ok,
                            message = "支付成功",

                        };
                    }

                }
                else
                {



                    var pay = order.Pay.Where(d => d.POID == order.OID && d.PResult == -1);


                    List<Dto.EF.Pay> pays = new List<Dto.EF.Pay>();

                    pay.ToList().ForEach(d =>
                    {
                        pays.Add(d);
                    });
                    pays.ForEach(d =>
                    {
                        d.PCards = null;
                        d.PResult = 1;
                    });






                    _payService.UpdateRange(pays);

                    var result = _payService.SaveChange();


                    if (result > 0)
                    {




                        _payService.SaveChange();

                        order.OState = 0;

                        order.OIsPay = 1;




                        List<Dto.EF.OrdersDetails> OrderDetails = order.OrdersDetails.ToList();

                        OrderDetails.ForEach(d =>
                        {
                            d.goods.Gnum -= d.ODCount;
                        });


                        _baseOrdersService.Update(order);
                        _baseOrdersService.SaveChange();

                        var table = _baseTableService.QueryAll(d => d.Tid == order.OTID).Single();
                        var iqy = _baseOrdersService.QueryAll(d => d.OTID == table.Tid && d.OState == 2 || d.OState == 3);

                        if (iqy.Any())
                        {
                            table.Toccupy -= order.Ooccupy;

                        }
                        else
                        {
                            table.Toccupy = 0;
                            table.Tstatus = 0;
                        }

                        _baseTableService.Update(table);
                        _baseTableService.SaveChange();

                        return new ApiResult()
                        {
                            code = ApiCode.ok,
                            message = "支付成功",

                        };
                    }

                }
            }
            return new ApiResult()
            {
                code = ApiCode.fail,
                message = "订单号错误"
            };

        }



        /// <summary>
        /// 余额支付
        /// </summary>
        /// <returns></returns>
        public ApiResult PayMyMoney(OrderRequestDto dto)
        {
            var iq = _baseOrdersService.QueryAll(d => d.OID == dto.id);

            if (iq.Any())
            {

                var order = iq.Single();

                Dto.EF.WxUser User = order.WxUser;
                if (User.Umoney < order.OMoney)
                {
                    return new ApiResult()
                    {
                        code = ApiCode.fail,
                        message = "你的余额不足"
                    };
                }



                Dto.EF.Pay pay = new Dto.EF.Pay();

                pay.PID = Common.Config.GUID();
                pay.POID = order.OID;
                //实付金额
                pay.PMoney = dto.PaidInMoney;
                pay.PCreateTime = DateTime.Now;
                //总金额
                pay.PSumMoney = dto.PaidInMoney;
                pay.PCards = null;

                pay.PResult = -1;
                pay.PType = dto.PayType;


                _payService.Add(pay);

                var result = _payService.SaveChange();


                if (result > 0)
                {
                    pay.PResult = 1;


                    _payService.Update(pay);
                    _payService.SaveChange();

                    order.OPayType = dto.PayType;
                    order.OState = 2;

                    order.OIsPay = 1;

                    User.Umoney -= order.OPaidInMoney;

                    var table = _baseTableService.QueryAll(d => d.Tid == order.OTID).Single();


                    table.Tstatus = 1;

                    _baseTableService.Update(table);

                    List<Dto.EF.OrdersDetails> OrderDetails = order.OrdersDetails.ToList();

                    OrderDetails.ForEach(d =>
                    {
                        d.goods.Gnum -= d.ODCount;
                        d.ODIsPay = 0;
                    });


                    _baseOrdersService.Update(order);
                    _baseOrdersService.SaveChange();



                    return new ApiResult()
                    {
                        code = ApiCode.ok,
                        message = "支付成功",

                    };
                }
                return new ApiResult()
                {
                    code = ApiCode.fail,
                    message = "支付失败"
                };



            }

            return new ApiResult()
            {
                code = ApiCode.fail,
                message = "订单号错误"
            };




        }



        /// <summary>
        /// 获取所有订单
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public ApiResult GetALLOrder(OrderRequestDto dto)
        {

            Expression<Func<Dto.EF.Orders, bool>> where = d => d.ONumBer.Contains(dto.key);


            if (dto.state != -1)
            {
                where = d => d.ONumBer.Contains(dto.key) && d.OState == dto.state;
            }

            var iq = _baseOrdersService.QueryAll(out int total, dto.page, dto.limit, o => o.OCreaTime, false, where);


            if (iq.Any())
            {
                var data = iq.Select(d => new Dto.Reponse.OrderResponseDto()
                {
                    id = d.OID,
                    count = d.OCount,
                    createTime = d.OCreaTime.Value.ToString(),
                    state = d.OState,
                    money = d.OMoney,
                    PayType = d.OPayType,
                    phone = d.OPhone,
                    occupy = d.Ooccupy,
                    Type = d.OType,
                    PaidInMoney = d.OPaidInMoney,
                    Number = d.ONumBer,
                    isPay = d.OIsPay,
                    TableName = d.tables.Tnumber,
                    UserName = d.WxUser.UName
                }).ToList();

                return new ApiResult()
                {

                    code = ApiCode.ok,
                    data = new
                    {
                        data = data,
                        total
                    },
                    message = "获取所有订单"
                };
            }


            return new ApiResult()
            {
                code = ApiCode.fail,
                data = new
                {
                    data = new List<Dto.Reponse.OrderResponseDto>(),
                    total = 0
                },
                message = "无订单",
            };


        }

        /// <summary>
        /// 获取订单详情
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public ApiResult GetALlDetails(OrderRequestDto dto)
        {
            var Orderiq = _baseOrdersService.QueryAll(d => d.OID == dto.id);

            if (Orderiq.Any())
            {
                var iq = _baseOrderDetailsService.QueryAll(d => d.ODOID == dto.id);

                var data = iq.Select(d => new Dto.Reponse.OrderDetailsResponseDto()
                {
                    isPay = d.ODIsPay,
                    count = d.ODCount,
                    flavor = new Dto.Reponse.flavorResponseDto()
                    {
                        id = d.flavor.Fid,
                        name = d.flavor.Fname,
                    },
                    good = new Dto.Reponse.GoodsResponseDto()
                    {
                        name = d.goods.Gname,
                        price = d.goods.Gprice,
                        img = d.goods.GImg
                    },
                    PayType = d.ODPayType
                }).ToList();

                return new ApiResult()
                {
                    code = ApiCode.ok,
                    message = "获取订单详情",
                    data = data
                };



            }


            return new ApiResult()
            {
                code = ApiCode.fail,
                message = "订单号错误",
            };


        }

        /// <summary>
        /// 获取支付详情
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public ApiResult GetAllPay(OrderRequestDto dto)
        {
            var Order = _baseOrdersService.QueryAll(d => d.OID == dto.id);
            if (Order.Any())
            {
                var iq = _payService.QueryAll(d => d.POID == dto.id);

                var data = iq.Select(d => new Dto.Reponse.PayResponseDto()
                {
                    id = d.PID,
                    OrderName = d.Orders.ONumBer,
                    cretetime = d.PCreateTime,
                    Money = d.PSumMoney,
                    Ptype = d.PType,
                    result = d.PResult,

                }).ToList();

                data.ForEach(d =>
                {
                    d.time = d.cretetime.Value.ToString("yyyy-MM-dd hh:mm:ss");
                });

                return new ApiResult()
                {
                    code = ApiCode.ok,
                    data = data
                };
            }
            return new ApiResult()
            {
                code = ApiCode.fail,
                message = "订单号不存在"
            };



        }




    }
}
